# utils.py

import requests
import subprocess
import logging
from models import CommitInfo

from sqlalchemy import desc
from models import CommitInfo
from models import Auth

from sqlalchemy import desc
from models import CommitInfo
from models import Auth

logger = logging.getLogger(__name__)

# 获取 OAuth2 token
def get_token(url, client_id, client_secret, code):
    try:
        payload = {
            'client_id': client_id,
            'client_secret': client_secret,
            'code': code
        }
        headers = {'Content-Type': 'application/x-www-form-urlencoded'}
        
        response = requests.post(url, data=payload, headers=headers)
        response.raise_for_status()
        return response.json()
    except requests.RequestException as e:
        logger.error(f"Failed to get token: {str(e)}")
        return {"error": str(e)}

# 获取用户信息
def get_user_info(access_token):
    try:
        headers = {
            'Authorization': f'Bearer {access_token}'
        }
        user_info_url = "https://api.atomgit.com//user/info"
        response = requests.get(user_info_url, headers=headers)
        response.raise_for_status()
        return response.json()
    except requests.RequestException as e:
        logger.error(f"Failed to get user info: {str(e)}")
        return {"error": str(e)}

def send_email(subject, body, recipient_email):
    """
    发送邮件通知
    使用命令行调用邮件发送脚本
    """
    if not recipient_email:
        logger.warning('未指定邮件接收人，跳过发送邮件。')
        return

    # 调用 send_email.py 异步发送邮件
    cmd = [
        'python', 'send_email.py',
        '--subject', subject,
        '--body', body,
        '--recipient', recipient_email
    ]
    try:
        subprocess.Popen(cmd)
        logger.info(f'发送邮件通知给 {recipient_email}')
    except Exception as e:
        logger.error(f'发送邮件失败: {e}')

def get_user_email(token):
    url = "https://api.atomgit.com/user/emails"
    headers = {
        "Content-Type": "application/json",
        "Authorization": f"Bearer {token}"
    }
    response = requests.get(url, headers=headers)

    if response.status_code >= 200 and response.status_code < 400:
        emails = response.json()
        for email_data in emails:
            if "email" in email_data:
                logger.info(f"Email: {email_data['email']}")
                return email_data["email"]
    else:
        logger.error(f"Error fetching user email: {response.status_code} - {response.text}")
        return None
    
# 检查 DCO 签名
def check_signed_off_by(message):
    return "Signed-off-by:" in message

# 获取 Signed-off-by 的信息
def get_signed_off_by(message):
    lines = message.split('\n')
    for line in lines:
        if line.startswith("Signed-off-by:"):
            parts = line.split('<')
            if len(parts) > 1:
                email = parts[1].replace('>', '')
                name = parts[0].replace('Signed-off-by:', '').strip()
                return name, email
    return None, None

def create_pr_labels(owner, repo, pull_number, token, labels):
    url = f"https://api.atomgit.com/repos/{repo}/pulls/{pull_number}/labels"
    data = {
        "label_name_list": labels
    }
    headers = {
        "Content-Type": "application/json",
        "Authorization": f"Bearer {token}"
    }
    response = requests.post(url, json=data, headers=headers)
    logger.info(f"url: {url}")

    if response.status_code >= 200 and response.status_code < 400:
        logger.info(f"Labels added to PR: {response.status_code}")
        return None
    else:
        logger.error(f"Error adding labels to PR: {response.status_code} - {response.text}")
        return response.text

def create_dco_labels(owner, repo, name, color, token):
    url = f"https://api.atomgit.com/repos/{owner}/{repo}/labels"
    data = {
        "name": name,
        "color": color
    }
    headers = {
        "Content-Type": "application/x-www-form-urlencoded",
        "Authorization": f"Bearer {token}"
    }
    response = requests.post(url, data=data, headers=headers)

    if response.status_code >= 200 and response.status_code < 400:
        logger.info(f"DCO Labels created successfully: {response.status_code}")
        return None
    else:
        logger.error(f"Error creating DCO Labels: {response.status_code} - {response.text}")
        return response.text

def get_dco_labels(owner, repo, token):
    url = f"https://api.atomgit.com/repos/{owner}/{repo}/labels"
    headers = {
        "Content-Type": "application/x-www-form-urlencoded",
        "Authorization": f"Bearer {token}"
    }
    response = requests.get(url, headers=headers)

    if response.status_code >= 200 and response.status_code < 400:
        labels = response.json()
        label_names = [label["name"] for label in labels]
        logger.info(f"DCO Labels: {label_names}")
        return label_names
    else:
        logger.error(f"Error fetching DCO Labels: {response.status_code} - {response.text}")
        return None

# 获取提交信息
def get_commits_info(owner, repo, commit_id, token):
    url = f"https://api.atomgit.com/repos/{repo}/commits/{commit_id}"
    logger.info(f"url: {url}")
    headers = {
        "Content-Type": "application/json",
        "Authorization": f"Bearer {token}"
    }
    response = requests.get(url, headers=headers)
    if response.status_code == 200:
        commit_data = response.json()
        logger.info(f"commit_data: {commit_data}")
        commit_info = CommitInfo(
            name=commit_data["commit"]["committer"]["name"],
            email=commit_data["commit"]["committer"]["email"],
            message=commit_data["message"]
        )
        logger.info(f"Commit Info: {commit_info.message}")
        return commit_info
    else:
        logger.error(f"Failed to fetch commit info: {response.status_code}")
        return None

# 发送评论
def create_pr_comment(owner, repo, pull_number, body, commit_id, token):
    url = f"https://api.atomgit.com/repos/{repo}/pulls/{pull_number}/comments"
    data = {
        "body": body,
        "commit_id": commit_id
    }
    logger.info(f"url: {url}")
    headers = {
        "Content-Type": "application/json",
        "Authorization": f"Bearer {token}"
    }
    response = requests.post(url, json=data, headers=headers)
    if response.status_code >= 200 and response.status_code < 400:
        logger.info("PR Comment created successfully")
        return None
    else:
        logger.error(f"Error in PR Comment creation: {response.status_code} - {response.text}")
        return response.text

# 处理合并事件
def handle_merge_event(req):
    action = req.get("action", "")
    logger.info(f"Received merge event: {req}")
    if action != "opened" and action != "synchronize":
        return {"code": 0, "message": "Not a valid merge action"}

    pull_request = req.get("pull_request", {})
    logger.info(f"The pull request: {pull_request}")
    if not pull_request:
        return {"code": 1, "message": "Invalid pull request data"}

    # 获取相关信息
    logger.info(f"Repository info: {req.get('repository', {})}")
    owner = req.get("repository", {}).get("owner", {}).get("login", "")
    repo = req.get("repository", {}).get("full_name", "")
    commit_id = pull_request.get("head", {}).get("sha", "")

    dco_owner = req.get("sender", {}).get("id", "")

    # 从数据库读取 token
    auth = Auth.query.filter_by(user_id=dco_owner).order_by(desc(Auth.create_at)).first() 
    if not auth:
        logger.error("Token not found in database.")
        return {"code": 1, "message": "Token not found in database"}
    
    token = auth.access_token
    logger.info(f"Using token: {token}")

    # Verify if the commit info is available
    commit_info = get_commits_info(owner, repo, commit_id, token)
    if commit_info:
        logger.info(f"Commit info fetched: {commit_info.message}")
    else:
        logger.error(f"Failed to fetch commit info for {commit_id} in {repo}")
        return {"code": 1, "message": "Failed to fetch commit info"}

    # 验证DCO签名
    lables = []
    if commit_info and check_signed_off_by(commit_info.message):
        name, email = get_signed_off_by(commit_info.message)
        if name and email:
            logger.info(f"Valid DCO signature: {name} <{email}>")
            create_pr_comment(owner, repo, pull_request['number'], "DCO验证结果: 验证通过", commit_id, token)
            lables.append("DCO Signed")
            create_pr_labels(owner, repo, pull_request['number'], token, lables)
            return {"code": 0, "message": "DCO validation passed"}
        else:
            logger.info("Invalid DCO signature")
            create_pr_comment(owner, repo, pull_request['number'], "DCO验证结果: 验证不通过", commit_id, token)
            lables.append("DCO Unsigned")
            create_pr_labels(owner, repo, pull_request['number'], token, lables)
            return {"code": 1, "message": "Invalid DCO signature"}

    # Return failure if DCO validation failed
    logger.error("DCO validation failed")
    create_pr_comment(owner, repo, pull_request['number'], "DCO验证结果: 验证不通过", commit_id, token)
    lables.append("DCO Unsigned")
    create_pr_labels(owner, repo, pull_request['number'], token, lables)
    return {"code": 1, "message": "DCO validation failed"}
